package com.liveinstars.im.domain.manager.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.liveinstars.api.im.query.FriendsQuery;
import com.liveinstars.im.domain.dao.mapper.FriendsMapper;
import com.liveinstars.im.domain.dao.model.Friends;
import com.liveinstars.im.domain.manager.FriendsManager;
import com.onepiece.shipelves.common.constant.Constant;
import com.onepiece.shipelves.common.enums.SystemExceptionEnum;
import com.onepiece.shipelves.common.exception.DatabaseException;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cglib.beans.BeanCopier;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * <p>
 * 朋友表 服务实现类
 * </p>
 *
 * @author 8btc
 * @since 2020-03-31
 */
@Service
public class FriendsManagerImpl extends ServiceImpl<FriendsMapper, Friends> implements FriendsManager {

    private final static Logger logger = LoggerFactory.getLogger(FriendsManagerImpl.class);

    @Override
    public List<Friends> listByUserIdAndUserFriendId(Long userId, Long userFriendId, Integer type) {
        try {
            QueryWrapper<Friends> queryWrapper = new QueryWrapper<>();
            queryWrapper.and(query -> query.eq("user_id", userId).eq("friend_id", userFriendId)
                    .or(query2 -> query2.eq("user_id", userFriendId).eq("friend_id", userId)))
                    .eq("state", Constant.STATE_VALID);
            if (type != null) {
                queryWrapper.eq("type", type);
            }
            List<Friends> list = this.list(queryWrapper);
            return list;
        } catch (Exception e) {
            logger.error("查询好友关系列表异常listByUserIdAndUserFriendId: params:{}, errorMsg:{}",
                    "userId="+userId+", userFriendId="+ userFriendId,
                    e.getMessage(), e);
            throw new DatabaseException(SystemExceptionEnum.MYSQL_OPERATING_ERROR);
        }
    }

    @Override
    public void saveFriends(Long applyUserId, Long acceptUserId, Integer type) {
        try {
            List<Friends> friendList = this.listByUserIdAndUserFriendId(applyUserId, acceptUserId, null);
            if (CollectionUtils.isNotEmpty(friendList)) {
                //好友关系补全
                if (friendList.size() < 2) {
                    Friends friends = friendList.get(0);
                    Friends newFriends = new Friends();
                    BeanCopier beanCopier = BeanCopier.create(Friends.class, Friends.class, false);
                    beanCopier.copy(friends, newFriends, null);
                    newFriends.setId(null);
                    friendList.add(newFriends);
                }
                friendList.stream().forEach(friends -> {
                    friends.setType(type);
                    friends.setState(Constant.STATE_VALID);
                    friends.setCstModified(LocalDateTime.now());
                });
            } else {
                friendList = Lists.newArrayList();
                Friends friends = initFriend(applyUserId, acceptUserId, type);
                friendList.add(friends);
                friends = initFriend(acceptUserId, applyUserId, type);
                friendList.add(friends);
            }
            this.saveOrUpdateBatch(friendList);
        } catch (Exception e) {
            logger.error("保存好友关系异常saveFriends：params:{}, errorMsg:{}",
                    "applyUserId="+applyUserId + ", acceptUserId="+ acceptUserId + ", type=="+ type,
                    e.getMessage(), e);
            throw new DatabaseException(SystemExceptionEnum.MYSQL_OPERATING_ERROR);
        }
    }

    @Override
    public List<Friends> listFriendsByUserIdAndType(Long userId, Integer type) {
        try {
            QueryWrapper<Friends> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", userId)
                    .eq("type", type)
                    .eq("state", Constant.STATE_VALID);
            return this.list(queryWrapper);
        } catch (Exception e) {
            logger.error("查询好友关系列表异常listFriendsByUserIdAndType：params:{}, errorMsg:{}",
                    "userId="+userId + ", type="+ type,
                    e.getMessage(), e);
            throw new DatabaseException(SystemExceptionEnum.MYSQL_OPERATING_ERROR);
        }
    }

    @Override
    public Friends getFriendsByUserIdAndFriendsId(Long userId, Long friendId) {
        try {
            QueryWrapper<Friends> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", userId)
                    .eq("friend_id", friendId)
                    .eq("state", Constant.STATE_VALID);
            List<Friends> list = this.list(queryWrapper);
            if (CollectionUtils.isNotEmpty(list)) {
                return list.get(0);
            }
            return null;
        } catch (Exception e) {
            logger.error("getFriendsByUserIdAndFriendsId：params:{}, errorMsg:{}",
                    "userId="+userId + ", friendId="+ friendId,
                    e.getMessage(), e);
            throw new DatabaseException(SystemExceptionEnum.MYSQL_OPERATING_ERROR);
        }
    }

    @Override
    public void deleteFriends(Long applyUserId, Long acceptUserId) {
        try {
            QueryWrapper<Friends> queryWrapper = new QueryWrapper<>();
            queryWrapper.and(query -> query.eq("user_id", applyUserId).eq("friend_id", acceptUserId)
                    .or(query2 -> query2.eq("user_id", acceptUserId).eq("friend_id", applyUserId)))
                    .eq("state", Constant.STATE_VALID);
            Friends friends = new Friends();
            friends.setState(Constant.STATE_INVALID);
            friends.setCstModified(LocalDateTime.now());
            this.update(friends, queryWrapper);
        } catch (Exception e) {
            logger.error("删除好友关系异常deleteFriends：params:{}, errorMsg:{}",
                    "applyUserId="+applyUserId + ", acceptUserId="+ acceptUserId,
                    e.getMessage(), e);
            throw new DatabaseException(SystemExceptionEnum.MYSQL_OPERATING_ERROR);
        }

    }

    @Override
    public void updateByQuery(Friends friends, FriendsQuery query) {
        if (query == null || friends == null) {
            throw new DatabaseException(SystemExceptionEnum.MISSING_REQUEST_PARAM);
        }
        try {
            QueryWrapper<Friends> queryWrapper = new QueryWrapper<>();
            if (query.getFriendId() != null) {
                queryWrapper.eq("friend_id", query.getFriendId());
            }
            if (query.getUserId() != null) {
                queryWrapper.eq("user_id", query.getUserId());
            }
            if (query.getType() != null) {
                queryWrapper.eq("type", query.getType());
            }
            queryWrapper.eq("state", Constant.STATE_VALID);
            this.update(friends, queryWrapper);
        } catch (Exception e) {
            logger.error("updateByQuery：params:{}, errorMsg:{}",
                    "friends="+ JSON.toJSONString(friends) + ", query="+ JSON.toJSONString(query),
                    e.getMessage(), e);
            throw new DatabaseException(SystemExceptionEnum.MYSQL_OPERATING_ERROR);
        }
    }

    @Override
    public void updateShield(Long applyUserId, Long shieldFriendId, boolean shield) {
        try {
            QueryWrapper<Friends> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("user_id", applyUserId)
                    .eq("friend_id", shieldFriendId)
                    .eq("state", Constant.STATE_VALID);
            Friends friends = new Friends();
            friends.setShield(shield);
            friends.setCstModified(LocalDateTime.now());
            this.update(friends, queryWrapper);
        } catch (Exception e) {
            logger.error("屏蔽好友关系异常updateShield：params:{}, errorMsg:{}",
                    "applyUserId="+applyUserId + ", shieldFriendId="+ shieldFriendId,
                    e.getMessage(), e);
            throw new DatabaseException(SystemExceptionEnum.MYSQL_OPERATING_ERROR);
        }
    }

    public Friends initFriend(Long applyUserId, Long acceptUserId, Integer type) {
        Friends friends = new Friends();
        friends.setUserId(applyUserId);
        friends.setFriendId(acceptUserId);
        friends.setType(type);
        friends.setCstCreated(LocalDateTime.now());
        friends.setCstModified(LocalDateTime.now());
        friends.setState(Constant.STATE_VALID);
        friends.setVisible(false);
        friends.setShield(false);
        return friends;
    }
}
